/**
 * 1. 和js不同的是模板字符串在ts中作为类型
 * 2. 模板字符串和联合类型一起使用 有交叉相乘效果
 * 3. 结合as可实现键名重映射。完成对象的get set方法
 * 4. 系统提供的操作模板字符串的工具类型
 * UpperCase<StringType>
 * LowerCase<StringType>
 * Capitalize<StringType>
 * Uncapitalize<StringType>

 */

// 1. 和js 不同的是模板字符串在ts中作为类型
type World = "world";
type Greeting = `hello ${World}`; // "hello world"

// 2. 模板字符串和联合类型一起使用 有交叉相乘的效果
type Direction = "left" | "right" | "top" | "bottom";
type BoxName = "padding" | "margin" | "border";
type BoxModel = `Box-${Direction}`; // Box-left | Box-right | Box-top | Box-bottom
type BoxModel2 = `${BoxName}-${Direction}`; // 3*4 = 12个的联合类型

// 3.实现键名重映射
const person = {
  firstName: "john",
  lastName: "Doe",
  age: 30,
};
// 3.1 写一个工具方法 类给所有的key添加Id后缀;
type AddId<T> = {
  [K in keyof T as `${K & string}Id`]: T[K];
};
type CId = AddId<typeof person>;

// 3.2 写一个工具方法 给对象中的属性添加 getter 和 setter
type AddGetter<T extends { [key: string]: any }> = {
  [K in keyof T as `get${Capitalize<K & string>}`]: () => T[K];
};
type AddSetter<T> = {
  [K in keyof T as `set${Capitalize<K & string>}`]: (e: T[K]) => void;
};
type AddGetterSetter<T extends object> = T & AddGetter<T> & AddSetter<T>;

type PersonWithGetterSetter = AddGetterSetter<typeof person>;
const person2: PersonWithGetterSetter = {
  firstName: "",
  setFirstName(e) {},
  getFirstName() {
    return "";
  },
  lastName: "",
  setLastName(e) {},
  getLastName() {
    return "";
  },
  age: 0,
  setAge(e) {},
  getAge() {
    return 1;
  },
};
